package xadrez;


import javax.swing.*;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class Jogo extends JPanel implements MouseListener{

    private Tabuleiro xadrezAtual;
    private Jogador A;
    private Jogador B;
    private char turno;
    private String estadoJogo;   
    private Point p;
    //1 para humano e 2 para cpu
    private int TipoJogadorA;
    private int TipoJogadorB;
    private int resolucao;
    private boolean mouseClick;
    private PlanoDeFundo planoFundo;   
    
    
    
    
    
    public Jogo() {        	
        super();           
        planoFundo = new PlanoDeFundo(640);
        xadrezAtual = new Tabuleiro();                       
        turno = 'a';
        mouseClick = false;
        resolucao = 640;
        this.addMouseListener(this);
        repaint();
        

    }   
    
    public Jogo(int resolucao) {
    	super();     	
        planoFundo = new PlanoDeFundo(resolucao);
        xadrezAtual = new Tabuleiro();                     
        turno = 'a';
        mouseClick = false;
        this.resolucao = resolucao;
        this.addMouseListener(this);
        repaint();
    }
    
    public Jogo(int resolucao, Tabuleiro tabuleiro) {
        super();    	
        planoFundo = new PlanoDeFundo(resolucao);
        xadrezAtual = tabuleiro;                    
        turno = 'a';
        mouseClick = false;
        this.resolucao = resolucao;
        this.addMouseListener(this);
        repaint();
    }
     
    
    @Override
    public void paintComponent(Graphics g) {
    	// TODO Auto-generated method stub
    	super.paintComponents(g);
    	planoFundo.Desenha(g, xadrezAtual);    	
    }
    
   @Override
   public void mouseClicked(MouseEvent arg0) {}
   
   @Override
  public void mouseEntered(MouseEvent e) {}
   
   
   @Override
   public void mouseExited(MouseEvent arg0) {}
   
   @Override
   public void mousePressed(MouseEvent e) {
       
      if (!mouseClick) {
          System.out.println("click!!!");
		   p = e.getPoint();
		   mouseClick = true;
	   }
   }
   
   @Override
   public void mouseReleased(MouseEvent arg0) {}
    
   public void iniciaCpuVsCpu() {
        repaint();    
        boolean auxiliar = true;
        String estadoJogo = "";
        
        String nomeA = "Jogador 1"; 
        String nomeB = "Jogador 2";
        A = new Jogador(nomeA, "branco");        
        B = new Jogador(nomeB, "preto");
        TipoJogadorA = 2;
        TipoJogadorB = 2;       

        while (auxiliar) {

            auxiliar = joga();            
           

        }

        estadoJogo = GetEstadoJogo();

        if (estadoJogo.equals("empate")) {

            JOptionPane.showMessageDialog(null, "JOGO EMPATOU");

        } else {

            JOptionPane.showMessageDialog(null, "    CHECKMATE!\n" + "  Jogador " + GetCorDaVez()
                    + " ganhou\n" + "   Parabens " + GetJogadorDaVez());

        }

  }
   
   public void iniciaPlayVsPlay() {
	   repaint();     
        boolean auxiliar = true;
        String estadoJogo = "";
        
        String nomeA = "Jogador 1"; 
        String nomeB = "Jogador 2";
        A = new Jogador(nomeA, "branco");        
        B = new Jogador(nomeB, "preto");
        TipoJogadorA = 1;
        TipoJogadorB = 1;
        
        while (auxiliar) {

            auxiliar = joga();           

        }

        estadoJogo = GetEstadoJogo();

        if (estadoJogo.equals("empate")) {

            JOptionPane.showMessageDialog(null, "JOGO EMPATOU");

        } else {

            JOptionPane.showMessageDialog(null, "    CHECKMATE!\n" + "  Jogador " + GetCorDaVez()
                    + " ganhou\n" + "   Parabens " + GetJogadorDaVez());

        }

  }
   
   public void iniciaPlayVsCpu() {
	   	repaint();     
        boolean auxiliar = true;
        String estadoJogo = "";
        
        String nomeA = "Jogador 1"; 
        String nomeB = "Jogador 2";
        A = new Jogador(nomeA, "branco");        
        B = new Jogador(nomeB, "preto");
        TipoJogadorA = 1;
        TipoJogadorB = 2;

        while (auxiliar) {

            auxiliar = joga();            

        }

        estadoJogo = GetEstadoJogo();

        if (estadoJogo.equals("empate")) {

            JOptionPane.showMessageDialog(null, "JOGO EMPATOU");

        } else {

            JOptionPane.showMessageDialog(null, "    CHECKMATE!\n" + "  Jogador " + GetCorDaVez()
                    + " ganhou\n" + "   Parabens " + GetJogadorDaVez());

        }

  }
   	
   public void setResolucao(int res) {
	    planoFundo = new PlanoDeFundo(res);
   		resolucao = res;
   	}
             
    public boolean joga() {
        boolean auxiliar = true;
        boolean checkMate = false;
        boolean empate = false;
        empate = VerificaEmpate();
            if (!empate) {
                FazerJogada();
                checkMate = VerificaCheckMate();
                if(!checkMate){
                    TrocarTurno();
                }
            }
        if (empate){
            estadoJogo = "empate";
            auxiliar = !empate;
        }
        if (checkMate){
            estadoJogo = "checkMate";
            auxiliar = !checkMate;
        }
        return auxiliar;
    }

    public void FazerJogada() {
    	
        if (this.turno == 'a') {
            if (this.TipoJogadorA == 1){
                FazerJogada2(A);
            }
            else{
                FazJogadaCpu(A.GetCor());
            }
        } else {
            if (this.TipoJogadorB == 1){
                FazerJogada2(B);
            }
            else{
                FazJogadaCpu(B.GetCor());
            }
        }
        repaint();
        try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
    }

    private void FazerJogada2(Jogador JogadorAtual) {
        boolean jogadaConcluida = false;
        boolean verificaCheck = false;
        boolean validaJogada = false;
        boolean validaJogada2 = false;
        boolean validaJogada3 = false;
        boolean validaJogada4 = false;
        boolean roque = false;
        Peca pecaAjuda1;
        Peca pecaAjuda2;
        int vetorInicial[] = new int[2];
        int vetorMovimento[] = new int[2];
        
        
        // Verificação para ver se inicialmente o jogador está em check
        verificaCheck = xadrezAtual.VerificaCheck(JogadorAtual.GetCor());
        if (verificaCheck) {
            JOptionPane.showMessageDialog(null, "Jogador " + JogadorAtual.GetCor() + " esta em cheque!");
        }
        while (!jogadaConcluida) {
            //Jogador seleciona X e Y
            while(!mouseClick) {
                try { 
                      Thread.sleep(200);
                } catch (InterruptedException ex) {
                       
                }
            }
            mouseClick = false;            
		// Implementar escolha da posi��o
            vetorInicial[0] = ((int)p.getX()) / (resolucao/8);
            vetorInicial[1] = ((int)p.getY()) / (resolucao/8);		
            validaJogada = xadrezAtual.VerificaValidade(vetorInicial[0], vetorInicial[1], JogadorAtual.GetCor());
            while (validaJogada & !jogadaConcluida) {
                //Jogador seleciona X e Y
                while(!mouseClick) {                    
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException ex) {
                        
                    }
                }
                mouseClick = false; 
        // Implementar escolha da posi��o
                vetorMovimento[0] = ((int)p.getX()) / (resolucao/8);
                vetorMovimento[1] = ((int)p.getY()) / (resolucao/8);		
                validaJogada2 = xadrezAtual.VerificaValidade(vetorMovimento[0], vetorMovimento[1], JogadorAtual.GetCor());

                //ValidaJogada2, ve se a segunda peça escolhida é da mesma coir da primeira
                //Então nesse bloco ele verifica se ocorre um ROQUE quando vc seleciona 2 peças com a mesma cor
                if (validaJogada2) {
                    roque = VerificaRoque(vetorInicial[0], vetorInicial[1], vetorMovimento[0], vetorMovimento[1]);
                    validaJogada2 = !roque;
                }

                if (validaJogada2) {
                    vetorInicial[0] = vetorMovimento[0];
                    vetorInicial[1] = vetorMovimento[1];
                } else {
                    //Verifica se é possivel mover a peça para as coordenadas escolhidas, 'verifica ROQUE', porem não verifica se você ficou em check
                    validaJogada3 = xadrezAtual.VerificaJogada(vetorInicial[0], vetorInicial[1], vetorMovimento[0], vetorMovimento[1]);
                    if (validaJogada3) {
                        pecaAjuda1 = xadrezAtual.GetPeca(vetorInicial[0], vetorInicial[1]);
                        pecaAjuda2 = xadrezAtual.GetPeca(vetorMovimento[0], vetorMovimento[1]);
                        xadrezAtual.FazJogada(vetorInicial[0], vetorInicial[1], vetorMovimento[0], vetorMovimento[1]);
                        //Verifica se a jogada não faz você ficar em check, sendo uma jogada invalida
                        validaJogada4 = !xadrezAtual.VerificaCheck(JogadorAtual.GetCor());
                        if (validaJogada4) {

                            //Entra aqui para ver se pode acontecer uma PROMOÇÃO,e se ocorre faz a devida troca.
                            VerificaPromocao(vetorMovimento[0], vetorMovimento[1]);

                            jogadaConcluida = true;
                            if(roque){
                                if(xadrezAtual.GetPeca(2, vetorInicial[1]).GetTipo() == 'k'){
                                    xadrezAtual.AdicionaMovimento(2, vetorInicial[1]);
                                }else{
                                    xadrezAtual.AdicionaMovimento(6, vetorInicial[1]);
                                }
                            }
                            else{
                                xadrezAtual.AdicionaMovimento(vetorMovimento[0], vetorMovimento[1]);
                            }
                        } else {
                            //Refaz a jogada, pois ela ocasionou um check no jogador atual
                            xadrezAtual.SetPeca(pecaAjuda1, vetorInicial[0], vetorInicial[1]);
                            xadrezAtual.SetPeca(pecaAjuda2, vetorMovimento[0], vetorMovimento[1]);
                        }
                    }
                }
            }
        }
       
    }
    
    
    private void FazJogadaCpu(String cor) {
        int vet[] = new int[5];
        vet = AlgoritimoMinMax(cor,1);
        //System.out.println("0:" + vet[0]);
        //System.out.println("1:" + vet[1]);
        //System.out.println("2:" + vet[2]);
        //System.out.println("3:" + vet[3]);
        //System.out.println("4:" + vet[4]);
        xadrezAtual.FazJogada(vet[0], vet[1], vet[2], vet[3]);
        //promoção!
        if ((vet[3] == 0) || (vet[3] == 7)) {
            if (xadrezAtual.GetPeca(vet[2], vet[3]).GetTipo() == 'p') {
                xadrezAtual.MudarPeao(vet[2], vet[3], 1);
            }
        }
    }

    private int[] AlgoritimoMinMax(String cor, int profundidade){
        //System.out.println("COR:" + cor);
        int vetMelhor[] = new int[5];
        vetMelhor[4] = -10000;
        //int vet[] = new int[4];
        int pontos;
        Peca pecaAjuda1;
        Peca pecaAjuda2;
        boolean validaJogada1;
        boolean validaJogada2;
        boolean validaJogada3;
        if (profundidade <= 1){
            for (int i = 0; i < 8; i++) {
                for (int j = 0; j < 8; j++) {
                    if (xadrezAtual.GetPeca(i, j).GetCor().equals(cor)){
                        for (int k = 0; k < 8; k++) {
                            for (int l = 0; l < 8; l++) {
                                if (!xadrezAtual.GetPeca(k, l).GetCor().equals(cor)){
                                    validaJogada2 = xadrezAtual.VerificaJogada(i, j, k, l);
                                    if (validaJogada2){
                                        pecaAjuda1 = xadrezAtual.GetPeca(i, j);
                                        pecaAjuda2 = xadrezAtual.GetPeca(k, l);
                                        xadrezAtual.FazJogada(i, j, k, l);
                                        //Verifica se a jogada não faz você ficar em check, sendo uma jogada invalida
                                        validaJogada3 = !xadrezAtual.VerificaCheck(cor);
                                        if (validaJogada3) {
                                            //Entra aqui para ver se pode acontecer uma PROMOÇÃO,e se ocorre faz a devida troca.
                                            if ((l == 0) || (l == 7)) {
                                                if (xadrezAtual.GetPeca(k, l).GetTipo() == 'p') {
                                                    xadrezAtual.MudarPeao(k, l, 1);
                                                }
                                            }
                                            pontos = xadrezAtual.AlgoritimoDeCusto(cor);
                                            if ( pontos > vetMelhor[4]){
                                                vetMelhor[0] = i;
                                                vetMelhor[1] = j;
                                                vetMelhor[2] = k;
                                                vetMelhor[3] = l;
                                                vetMelhor[4] = pontos;
                                            }
                                            xadrezAtual.SetPeca(pecaAjuda1, i, j);
                                            xadrezAtual.SetPeca(pecaAjuda2, k, l);
                                        } else {
                                            //Refaz a jogada, pois ela ocasionou um check no jogador atual
                                            xadrezAtual.SetPeca(pecaAjuda1, i, j);
                                            xadrezAtual.SetPeca(pecaAjuda2, k, l);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

        }
        return vetMelhor;
    }

    public void TrocarTurno() {
        if (this.turno == 'a') {
            this.turno = 'b';
        } else {
            this.turno = 'a';
        }
    }

    public boolean VerificaEmpate() {
        boolean empateLocal;
        if (this.turno == 'a') {
            empateLocal = VerificaEmpate2(A.GetCor());
            System.out.println("Jogador da vez: ".concat(A.GetNome()));
            System.out.println("");            
        } else {
            empateLocal = VerificaEmpate2(B.GetCor());
            System.out.println("Jogador da vez: ".concat(B.GetNome()));
            System.out.println("");            
        }
        return empateLocal;
    }

    private boolean VerificaEmpate2(String cor) {
        boolean empateLocal = true;
        int i = 0;
        int j = 0;
        while ((i < 8) & (empateLocal)) {
            j = 0;
            while ((j < 8) & (empateLocal)) {
                empateLocal = !xadrezAtual.VerificaPossibilidade(i, j, cor);
                j++;
            }
            i++;
        }
        return empateLocal;
    }

    public boolean VerificaCheckMate() {
        boolean checkParcecial;
        boolean retorno = false;
        if (this.turno == 'a') {
            checkParcecial = xadrezAtual.VerificaCheck(B.GetCor());
            if (checkParcecial) {
                retorno = xadrezAtual.ConfirmaCheckMate(B.GetCor());
            }
        } else {
            checkParcecial = xadrezAtual.VerificaCheck(A.GetCor());
            if (checkParcecial) {
                retorno = xadrezAtual.ConfirmaCheckMate(A.GetCor());
            }
        }
        return retorno;
    }

    private void VerificaPromocao(int x, int y) {
        if ((y == 0) || (y == 7)) {
            if (xadrezAtual.GetPeca(x, y).GetTipo() == 'p') {
                int tipo = Integer.parseInt(JOptionPane.showInputDialog("Escolha uma peça para substituir:\n1-Rainha\n2-Torre\n3-Bispo\n4-Cavalo"));
                xadrezAtual.MudarPeao(x, y, tipo);
            }
        }
    }

    private boolean VerificaRoque(int x, int y, int a, int b) {
        boolean podeRoque = false;
        if ((xadrezAtual.GetPeca(x, y).GetTipo() == 'k') & (xadrezAtual.GetPeca(x, y).GetMovimentos() == 0)) {
            if ((xadrezAtual.GetPeca(a, b).GetTipo() == 't') & (xadrezAtual.GetPeca(a, b).GetMovimentos() == 0)) {
                String corAtual = GetCorDaVez();
                if (corAtual.equals("branco")){
                    corAtual = "preto";
                }
                else{
                    corAtual = "branco";
                }
                if (a == 0) {
                    if ((xadrezAtual.GetPeca((a+1), b).GetTipo() == 'x') & (xadrezAtual.GetPeca((a+2), b).GetTipo() == 'x') & (xadrezAtual.GetPeca((a+3), b).GetTipo() == 'x')) {
                        if(!xadrezAtual.VerificaCasaAmeacada(a+1,b,corAtual)){
                            if(!xadrezAtual.VerificaCasaAmeacada(a+2,b,corAtual)){
                                if(!xadrezAtual.VerificaCasaAmeacada(a+3,b,corAtual)){
                                    podeRoque = true;
                                }   
                            }
                        }
                    }
                }
                else {
                    if ((xadrezAtual.GetPeca((a-1), b).GetTipo() == 'x') & (xadrezAtual.GetPeca((a-2), b).GetTipo() == 'x')) {
                        if(!xadrezAtual.VerificaCasaAmeacada(a-1,b,corAtual)){
                            if(!xadrezAtual.VerificaCasaAmeacada(a-2,b,corAtual)){
                                podeRoque = true;
                            }
                        }
                    }
                }
            }
        }
        return podeRoque;
    }

    public String GetJogadorDaVez() {
        String nome;
        if (this.turno == 'a') {
            nome = A.GetNome();
        } else {
            nome = B.GetNome();
        }
        return nome;
    }

    public String GetCorDaVez() {
        String cor;
        if (this.turno == 'a') {
            cor = A.GetCor();
        } else {
            cor = B.GetCor();
        }
        return cor;
    }
    
    
    public String GetEstadoJogo() {
        return estadoJogo;
    }
    
    public void criaTabuleiro() {    	
    	xadrezAtual.limpaTabuleiro();
    	Sprite imagem[] = new Sprite[13];
    	imagem[0] = new Sprite('b',"preto",resolucao);
    	imagem[1] = new Sprite('c',"preto",resolucao);
    	imagem[2] = new Sprite('k',"preto",resolucao);
    	imagem[3] = new Sprite('p',"preto",resolucao);
    	imagem[4] = new Sprite('q',"preto",resolucao);
    	imagem[5] = new Sprite('t',"preto",resolucao);		
    	imagem[6] = new Sprite('b',"branco",resolucao);
    	imagem[7] = new Sprite('c',"branco",resolucao);
    	imagem[8] = new Sprite('k',"branco",resolucao);
    	imagem[9] = new Sprite('p',"branco",resolucao);
    	imagem[10] = new Sprite('q',"branco",resolucao);
    	imagem[11] = new Sprite('t',"branco",resolucao);
    	imagem[12] = null;
    	
    	boolean finaliza = false;
    	
    	while(!finaliza) {
    		
    	}
    	
    	
    }
   
      
}
